#include "FKMenuInterface.h"

#include "FKVisualInterfaceView.h"
#include "FKQuickRowModel.h"
#include "FKAppVersionModel.h"

#include <QQuickItem>
#include <QQmlContext>
#include <QStringListModel>
#include <QSortFilterProxyModel>

#include "FKLogger.h"
#include "FKManagerType.h"
#include "FKModelRole.h"
#include "FKOSType.h"

FKMenuInterface::FKMenuInterface(QObject* parent):FKVisualInterface(parent){
    FK_CBEGIN
    _currentUsersModel=new QStringListModel(this);
    _avaliableUsersModel=new QStringListModel(this);
    _roomList=new FKQuickRowModel(this);
    _appVersionModel=new FKAppVersionModel(this);
    _filterModel=new QSortFilterProxyModel(this);
    _filterModel->setFilterRole(FKModelRole::osTypeRole);
    _filterModel->setSourceModel(_appVersionModel);
    _filterModel->setFilterRegExp(_appVersionModel->property("filteringExpr").toString());
    FK_CEND
}

FKMenuInterface::~FKMenuInterface(){
    FK_DBEGIN
    FK_DEND
}

void FKMenuInterface::setAvaliableRoomTypes(const QStringList &lst){
    _avaliableRoomTypes=lst;
    emit avaliableRoomsChanged();
}

FKVisualInterfaceView* FKMenuInterface::initialization(QWindow *parent){
    return new FKVisualInterfaceView(QString("FKVisualInterfaces/FKMenuInterface.qml"),parent);
}

void FKMenuInterface::setupDefaults(){
    FKVisualInterface::setupDefaults();
    QObject* obj=view()->rootObject();
    connect(this,FKQmlSignal2(addLang),obj,FKQmlSignal2(eAddLang));
    connect(this,SIGNAL(langRequest()),obj,SIGNAL(eLang()));
    connect(obj,FKQmlSignal1(languageChosen),this,FKQmlSignal1(languageChosen));
    connect(obj,SIGNAL(resetManagerRequested()),SLOT(resetManagerRequested()));
    connect(obj,SIGNAL(localManagerRequested()),SLOT(localManagerRequested()));
    connect(obj,FKQmlSignal1(serverManagerRequested),FKQmlSlot1(serverManagerRequested));
    connect(obj,FKQmlSignal2(clientManagerRequested),FKQmlSlot2(clientManagerRequested));
    connect(obj,FKQmlSignal1(createUserRequested),FKQmlSlot1(createUserRequest));
    connect(obj,FKQmlSignal1(deleteUserRequested),FKQmlSlot1(deleteUserRequest));
    connect(obj,FKQmlSignal1(addUserRequested),FKQmlSlot1(addUserRequest));
    connect(obj,FKQmlSignal1(removeUserRequested),FKQmlSlot1(removeUserRequest));
    connect(obj,SIGNAL(usersApply()),SIGNAL(usersApply()));
    connect(obj,FKQmlSignal4(createRoom),FKQmlSlot4(createRoomRequest));
    connect(obj,FKQmlSignal1(enterRoom),FKQmlSlot1(enterRoomRequest));
    connect(obj,SIGNAL(updateRoomList()),SIGNAL(updateRoomList()));
    connect(obj,FKQmlSignal3(genClient),FKQmlSlot3(genClientRequest));
    connect(obj,FKQmlSignal2(chooseClient),FKQmlSlot2(chooseClientRequest));
    connect(this,SIGNAL(toMainMenuRequest()),obj,SIGNAL(eMainMenu()));
    connect(this,SIGNAL(fromMainMenuRequest()),obj,SIGNAL(eHideMainMenu()));
    connect(this,SIGNAL(toClientMenuRequest()),obj,SIGNAL(eClientMenu()));
    connect(this,SIGNAL(fromClientMenuRequest()),obj,SIGNAL(eHideClientMenu()));
    connect(this,SIGNAL(toUserMenuRequest()),obj,SIGNAL(eUserMenu()));
    connect(this,SIGNAL(fromUserMenuRequest()),obj,SIGNAL(eHideUserMenu()));
    connect(this,SIGNAL(toRoomListRequest()),obj,SIGNAL(eRoomList()));
    connect(this,SIGNAL(fromRoomListRequest()),obj,SIGNAL(eHideRoomList()));
    connect(this,SIGNAL(toAppUpdateMenuRequest()),obj,SIGNAL(eAppUpdateMenu()));
    connect(this,SIGNAL(fromAppUpdateMenuRequest()),obj,SIGNAL(eHideAppUpdateMenu()));

    connect(obj,SIGNAL(download()),SLOT(downloadRequest()));
    connect(obj,SIGNAL(restart()),SLOT(restartRequest()));
    connect(obj,SIGNAL(interruptDownloading()),SIGNAL(downloadInterruptionRequested()));
    connect(obj,SIGNAL(skip()),SLOT(skipRequest()));
}

void FKMenuInterface::setupContextProperties(QQmlContext *context){
    FKVisualInterface::setupContextProperties(context);
    context->setContextProperty("currentUsersModel",QVariant::fromValue(_currentUsersModel));
    context->setContextProperty("avaliableUsersModel",QVariant::fromValue(_avaliableUsersModel));
    context->setContextProperty("roomListModel",QVariant::fromValue(_roomList));
    context->setContextProperty("appVersionModel",QVariant::fromValue(_appVersionModel));
    context->setContextProperty("appVersionFilteredModel",QVariant::fromValue(_filterModel));
}

void FKMenuInterface::addLang(QString lng, QString lngLbl){
    emit addLang(FKQmlArgument(lng),FKQmlArgument(lngLbl));
}

void FKMenuInterface::toLangMenu(){
    emit langRequest();
}

void FKMenuInterface::toMainMenu(){
    emit toMainMenuRequest();
}

void FKMenuInterface::fromMainMenu(){
    emit fromMainMenuRequest();
}

void FKMenuInterface::toClientMenu(){
    emit toClientMenuRequest();
}

void FKMenuInterface::fromClientMenu(){
    emit fromClientMenuRequest();
}

void FKMenuInterface::toUserMenu(){
    emit toUserMenuRequest();
}

void FKMenuInterface::fromUserMenu(){
    emit fromUserMenuRequest();
}

void FKMenuInterface::toRoomList(){
    emit toRoomListRequest();
}

void FKMenuInterface::fromRoomList(){
    emit fromRoomListRequest();
}

void FKMenuInterface::toAppUpdateMenu(){
    emit toAppUpdateMenuRequest();
}

void FKMenuInterface::fromAppUpdateMenu(){
    emit fromAppUpdateMenuRequest();
}

void FKMenuInterface::setUpdateFilesList(QStringList files,
                                         QList<quint8> osTypes,
                                         QStringList serverVersions,
                                         QList<qint64> serverWeights,
                                         QStringList localVersions,
                                         QList<qint64> localWeights){
    QList<QMap<int,QVariant> > src;
    int size=files.size();
    for(int i=0;i<size;++i){
        QMap<int,QVariant> m;
        m[FKModelRole::fileVName]=files.at(i);
        m[FKModelRole::osTypeRole]=osTypes.at(i);
        m[FKModelRole::hostVersion]=serverVersions.at(i);
        m[FKModelRole::hostWeight]=serverWeights.at(i);
        m[FKModelRole::hostWeightLbl]=FKAppVersionModel::bytesToLabelText(serverWeights.at(i));
        m[FKModelRole::clientVersion]=localVersions.at(i);
        m[FKModelRole::clientWeight]=localWeights.at(i);
        m[FKModelRole::clientWeightLbl]=FKAppVersionModel::bytesToLabelText(localWeights.at(i));
        m[FKModelRole::downloadedSize]=0;
        m[FKModelRole::downloadedWeightLbl]=FKAppVersionModel::bytesToLabelText(0);
        m[FKModelRole::needRE]=false;
        m[FKModelRole::allowRE]=false;
        if(serverVersions.at(i)!=QString() && serverWeights.at(i)){
            m[FKModelRole::allowDL]=true;
            m[FKModelRole::needDL]=(osTypes.at(i)==FKOSType::curOS);
        }else{
            m[FKModelRole::allowDL]=false;
            m[FKModelRole::needDL]=false;
        }
        src.append(m);
    }
    _appVersionModel->setSource(src);
    _appVersionModel->refreshDownloadedWeights();
    _appVersionModel->refreshDownloadWeights();
}

void FKMenuInterface::localManagerRequested(){
    emit managerRequested(FKManagerType::single,QString(),0);
//    FK_MLOG("local")
}

void FKMenuInterface::serverManagerRequested(FKQmlArgument port){
    emit managerRequested(FKManagerType::host,QString(),port.toInt());
//    FK_MLOG("server")
}

void FKMenuInterface::clientManagerRequested(FKQmlArgument ip, FKQmlArgument port){
    emit managerRequested(FKManagerType::client,ip.toString(),port.toInt());
//    FK_MLOG("client")
}

void FKMenuInterface::resetManagerRequested(){
    emit managerRequested(FKManagerType::none,QString(),0);
}

void FKMenuInterface::refreshClientAvaliableUsers(QStringList usr){
    _avaliableUsersModel->setStringList(usr);
}

void FKMenuInterface::refreshClientCurrentUsers(QStringList usr){
    _currentUsersModel->setStringList(usr);
}

void FKMenuInterface::createUserRequest(FKQmlArgument userName){
    emit createUserRequested(userName.toString());
}

void FKMenuInterface::deleteUserRequest(FKQmlArgument userName){
    emit deleteUserRequested(userName.toString());
}

void FKMenuInterface::addUserRequest(FKQmlArgument userName){
    emit addUserRequested(userName.toString());
}

void FKMenuInterface::removeUserRequest(FKQmlArgument userName){
    emit removeUserRequested(userName.toString());
}

void FKMenuInterface::createRoomRequest(FKQmlArgument roomType, FKQmlArgument roomName, FKQmlArgument roomDescription, FKQmlArgument roomPassword){
    emit createRoomRequested(roomType.toString(),roomName.toString(),roomDescription.toString(),roomPassword.toString());
}

void FKMenuInterface::enterRoomRequest(FKQmlArgument roomID){
    emit enterRoomRequested(roomID.toInt());
}

void FKMenuInterface::setRoomList(QList<QMap<int, QVariant> > lst){
    _roomList->setSource(lst);
}

void FKMenuInterface::genClientRequest(FKQmlArgument clientName, FKQmlArgument password, FKQmlArgument validator){
    emit genClientRequested(clientName.toString(),password.toString(),FKQmlArgumentToVariant(validator));
}

void FKMenuInterface::chooseClientRequest(FKQmlArgument clientName, FKQmlArgument password){
    emit chooseClientRequested(clientName.toString(),password.toString());
}

void FKMenuInterface::skipRequest(){
    fromAppUpdateMenu();
    toUserMenu();
}

void FKMenuInterface::downloadRequest(){
    const QVariant t(true);
    QList<QVariant> files=_appVersionModel->filterData(FKModelRole::fileVName,FKModelRole::needDL,t);
    QList<QVariant> osTypes=_appVersionModel->filterData(FKModelRole::osTypeRole,FKModelRole::needDL,t);
    int s=files.count();
    for(int i=0;i<s;++i){
        emit appFileUpdate(files.at(i).toString(),osTypes.at(i).toUInt());
    }
}

void FKMenuInterface::restartRequest(){
    const QVariant t(true);
    QList<QVariant> files=_appVersionModel->filterData(FKModelRole::fileVName,FKModelRole::needDL,t);
    QList<QVariant> osTypes=_appVersionModel->filterData(FKModelRole::osTypeRole,FKModelRole::needDL,t);
    int s=files.count();
    QStringList flist;
    QList<quint8> olist;
    for(int i=0;i<s;++i){
        flist.append(files.at(i).toString());
        olist.append(osTypes.at(i).toUInt());
    }
    emit appFilesReplace(flist,olist);
}

void FKMenuInterface::setDownloaded(QString file, quint8 osType, qint64 size){
    _appVersionModel->setDownloaded(file,osType,size);
}

void FKMenuInterface::setDownloadComplete(QString file, quint8 osType, bool success){
    _appVersionModel->setDownloadComplete(file,osType,success);
}
